package conson.tech.manage.coupons.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import conson.tech.core.exception.BaseException;
import conson.tech.core.response.Response;
import conson.tech.manage.common.constant.BusinessMessage;
import conson.tech.manage.common.util.TimeUtils;
import conson.tech.manage.coupons.constant.CouponsConstants;
import conson.tech.manage.coupons.entity.dto.*;
import conson.tech.manage.coupons.entity.pojo.CouponsBatch;
import conson.tech.manage.coupons.entity.pojo.CouponsCenter;
import conson.tech.manage.coupons.entity.pojo.OperationLog;
import conson.tech.manage.coupons.entity.vo.CouponsBatchCenterVo;
import conson.tech.manage.coupons.entity.vo.CouponsCenterVo;
import conson.tech.manage.coupons.mapper.CouponsBatchMapper;
import conson.tech.manage.coupons.mapper.CouponsCenterMapper;
import conson.tech.manage.coupons.mapper.CouponsMessageCenterMapper;
import conson.tech.manage.coupons.mapper.OperationLogMapper;
import conson.tech.manage.coupons.service.CouponsCenterService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

/**
 * ClassName: CouponsCenterServiceImpl
 * Description:
 * Author: ZYF
 * Date: 2020/7/21
 * Version: 1.0
 */
@Slf4j
@Service
public class CouponsCenterServiceImpl implements CouponsCenterService {

    @Autowired
    private CouponsCenterMapper couponsCenterMapper;

    @Autowired
    private CouponsBatchMapper couponsBatchMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private OperationLogMapper operationLogMapper;

    @Autowired
    private CouponsMessageCenterMapper couponsMessageCenterMapper;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 根据领券类型查询配置中心数据
     * zyf
     * 2020/7/23
     *
     * @param couponsType 领券配置类型
     */
    @Override
    public List<CouponsCenterVo> queryList(Integer couponsType) {


        log.info("查询领券配置中心列表");

        List<CouponsCenterVo> list = this.couponsCenterMapper.queryList(couponsType);

        log.info("结束查询领券中心配置");
        return list;
    }

    /**
     * 根据搜索条件查询优惠券列表
     * zyf
     * 2020/7/23
     *
     * @param pageIndex
     * @param pageSize
     * @param dto
     */
    @Override
    public Page<CouponsBatchCenterVo> queryCouponsList(Integer pageSize, Integer pageIndex, CouponsCenterDto dto) {


        log.info("开始查询优惠券批次列表");

        //构建分页查询条件
        Page<CouponsBatchCenterVo> page = new Page<>(pageIndex, pageSize);

        page = this.couponsBatchMapper.queryCouponsList(page, dto);

        log.info("结束查询优惠券批次列表");
        return page;
    }

    /**
     * 新增限时抢活动配置
     * zyf
     * 2020/7/23
     */
    @Override
    @Transactional
    public Response addTimeCouponsCenter(CouponsCenterAddTimeDto dto, Long userId, String currentUsername) {


        log.info("开始新增限时抢优惠券配置");
        CouponsBatch couponsBatch = this.couponsBatchMapper.selectById(dto.getCouponsId());
//        参数校验
        validParam(dto, couponsBatch);
        CouponsCenter center = new CouponsCenter();
        center.setActivityId(-1);
        center.setApplyId(userId);
        center.setBeginTime(dto.getBeginTime());
        center.setStartTime(dto.getStartTime());
        center.setEndTime(dto.getEndTime());
        //1 限时抢  2领券
        center.setCouponsType(1);


        center.setBatchName(dto.getBatchName());
        center.setBatchId(dto.getCouponsId());
//        每日秒杀总量
        center.setTotalNum(dto.getTotalNum());

        center.setLimitNum(dto.getLimitNum());
        center.setOrderSrot(dto.getOrderSrot());

        center.setCreateBy(userId);
        center.setCreateTime(LocalDateTime.now());

        this.couponsCenterMapper.insert(center);

        //            记录日志惠券数据修改日志
        //优惠券修改完成之后，录入优惠券操作日志表
        OperationLogDto opera1 = new OperationLogDto();
        opera1.setCreateBy(currentUsername);
        opera1.setDomainId(center.getId());
        opera1.setOperateDesc("新增限时抢活动");
        this.editActivityLog(opera1);

        //         定时任务开启后，每天将限时抢的数量存放到redis中,有效期结束后将剩余数量放回优惠券批次中，其他时候保证每日抢购库存为最大数
//         定时任务开启后，每天将限时抢的数量存放到redis中
        if (dto.getTotalNum() > couponsBatch.getStockNum()) {
            redisTemplate.opsForValue().set(CouponsConstants.ACTIVITY_COUPON_PREFIX + "-1" + ":" + dto.getCouponsId() + ":" + center.getId(), couponsBatch.getStockNum().toString());
            //            修改优惠券批次数量
            couponsBatch.setStockNum(0);
            couponsBatch.setUpdateBy(userId);
            couponsBatch.setUpdateTime(LocalDateTime.now());
            this.couponsBatchMapper.updateById(couponsBatch);

            //            记录日志惠券数据修改日志
            //优惠券修改完成之后，录入优惠券操作日志表
            OperationLogDto opera2 = new OperationLogDto();
            opera2.setCreateBy(currentUsername);
            opera2.setDomainId(couponsBatch.getId());
            opera2.setOperateDesc("修改优惠券");
            this.editLog(opera2);
        } else {
            redisTemplate.opsForValue().set(CouponsConstants.ACTIVITY_COUPON_PREFIX + "-1" + ":" + dto.getCouponsId() + ":" + center.getId(), dto.getTotalNum().toString());
            //            修改优惠券批次数量
            couponsBatch.setStockNum(couponsBatch.getStockNum() - dto.getTotalNum());
            couponsBatch.setUpdateBy(userId);
            couponsBatch.setUpdateTime(LocalDateTime.now());
            this.couponsBatchMapper.updateById(couponsBatch);

            //            记录日志惠券数据修改日志
            //优惠券修改完成之后，录入优惠券操作日志表
            OperationLogDto opera = new OperationLogDto();
            opera.setCreateBy(currentUsername);
            opera.setDomainId(couponsBatch.getId());
            opera.setOperateDesc("修改优惠券");
            this.editLog(opera);
        }


        log.info("结束新增限时抢优惠券配置");
        return Response.success(center.getId());

    }

    /**
     * 参数校验
     *
     * @param dto
     * @param couponsBatch
     * @return void
     */
    private void validParam(CouponsCenterAddTimeDto dto, CouponsBatch couponsBatch) {
        //                    校验优惠券批次信息是否存在
        if (couponsBatch == null) {
            throw new BaseException(BusinessMessage.COUPONS_NOT_EXISTS_ERROR);
        }
        //                校验券批次的数量是否大于0
        if (couponsBatch.getStockNum() <= 0) {
            throw new BaseException(BusinessMessage.COUPON_BATCH_NOT_ENOUGH_ERROR);
        }
//        如果全批次有效期为绝对日期：券批次有效期开始时间=<活动有效期<=券批次有效期结束时间
        if (couponsBatch.getStartTime() != null && couponsBatch.getEndTime() != null) {
            boolean res = !((dto.getStartTime().isAfter(couponsBatch.getStartTime().toLocalDate()) || dto.getStartTime().isEqual(couponsBatch.getStartTime().toLocalDate())) && (dto.getEndTime().isBefore(couponsBatch.getEndTime().toLocalDate()) || dto.getEndTime().isEqual(couponsBatch.getEndTime().toLocalDate())));
            //       校验批次券的有效期在活动的有效期间
            if (res) {
                throw new BaseException(BusinessMessage.COUPON_TIME_OUT_ERROR);
            }
        }
        //        单用户发放数量必须小于优惠券每人最大可领取数量
        if (dto.getLimitNum() > couponsBatch.getLimitNum() || dto.getLimitNum() <= 0) {
            throw new BaseException(BusinessMessage.COUPON_NUM_ERROR);
        }
        //                校验活动总数量不能超过优惠券剩余数量
//        long res1 = dto.getStartTime().toEpochDay() - dto.getEndTime().toEpochDay();
//        Integer count = Math.toIntExact(res1 * dto.getTotalNum());
//        if (dto.getLimitNum() > couponsBatch.getStockNum()) {
//            throw new BaseException(BusinessMessage.Activity_NUM_ERROR);
//        }
    }

    /**
     * 参数校验
     *
     * @param dto
     * @param couponsBatch
     * @return void
     */
    private void validParamReceive(CouponsCenterAddReceiveDto dto, CouponsBatch couponsBatch) {
        //                    校验优惠券批次信息是否存在
        if (couponsBatch == null) {
            throw new BaseException(BusinessMessage.COUPONS_NOT_EXISTS_ERROR);
        }
        //                校验券批次的数量是否大于0
        if (couponsBatch.getStockNum() <= 0) {
            throw new BaseException(BusinessMessage.COUPON_BATCH_NOT_ENOUGH_ERROR);
        }
//        券批次有效期开始时间=<活动有效期<=券批次有效期结束时间
        if (couponsBatch.getStartTime() != null && couponsBatch.getEndTime() != null) {
            boolean res = !((dto.getStartTime().isAfter(couponsBatch.getStartTime().toLocalDate()) || dto.getStartTime().isEqual(couponsBatch.getStartTime().toLocalDate())) && (dto.getEndTime().isBefore(couponsBatch.getEndTime().toLocalDate()) || dto.getEndTime().isEqual(couponsBatch.getEndTime().toLocalDate())));
            //       校验批次券的有效期在活动的有效期间
            if (res) {
                throw new BaseException(BusinessMessage.COUPON_TIME_OUT_ERROR);
            }
        }

        //        单用户发放数量必须小于优惠券每人最大可领取数量
        if (dto.getLimitNum() > couponsBatch.getLimitNum() || dto.getLimitNum() <= 0) {
            throw new BaseException(BusinessMessage.COUPON_NUM_ERROR);
        }
        //                校验活动总数量不能超过优惠券剩余数量
        if (dto.getCountNum() > couponsBatch.getStockNum()) {
            throw new BaseException(BusinessMessage.Activity_NUM_ERROR);
        }
    }


    /**
     * 删除一条优惠券限时抢配置信息
     * zyf
     * 2020/7/23
     *
     * @param id 优惠券批次id
     */
    @Override
    @Transactional
    public Response delTimeCouponsCenter(Long userId, String currentUsername, Long id) {


        log.info("开始删除限时抢优惠券");

        //            查询出领券活动信息
        CouponsCenter couponsCenter = this.couponsCenterMapper.selectOne(new QueryWrapper<CouponsCenter>().eq("id", id).eq("is_delete", 0));
        if (couponsCenter == null) {
            throw new BaseException(BusinessMessage.ACTIVITY_CENTER_TIME_NOT_EXISTS_ERROR);
        }
        //            活动开始前才能删除
        if (LocalDateTime.now().isAfter(TimeUtils.getTodayPlusHour(couponsCenter.getStartTime(), couponsCenter.getBeginTime().getHour()))) {
            throw new BaseException(BusinessMessage.ACTIVITY_CENTER_TIME_GOING_ERROR);
        }
//          TODO  同时要停止定时任务

        couponsCenter.setUpdateBy(userId);
        couponsCenter.setUpdateTime(LocalDateTime.now());
        couponsCenter.setIsDelete(1);

        this.couponsCenterMapper.updateById(couponsCenter);

//            记录日志惠券数据修改日志
        //优惠券修改完成之后，录入优惠券操作日志表
        OperationLogDto opera1 = new OperationLogDto();
        opera1.setCreateBy(currentUsername);
        opera1.setDomainId(couponsCenter.getId());
        opera1.setOperateDesc("删除限时抢活动");
        this.editActivityLog(opera1);

        //        同时将限时抢活动的剩余库存归还
        String remainNum = redisTemplate.opsForValue().get(CouponsConstants.ACTIVITY_COUPON_PREFIX + "-1" + ":" + couponsCenter.getBatchId() + ":" + couponsCenter.getId());
        CouponsBatch couponsBatch = this.couponsBatchMapper.selectById(couponsCenter.getBatchId());
        if (remainNum != null) {
            //            修改优惠券批次数量
            couponsBatch.setStockNum(couponsBatch.getStockNum() + Integer.parseInt(remainNum));
            couponsBatch.setUpdateBy(userId);
            couponsBatch.setUpdateTime(LocalDateTime.now());
            this.couponsBatchMapper.updateById(couponsBatch);

            //            记录日志惠券数据修改日志
            //优惠券修改完成之后，录入优惠券操作日志表
            OperationLogDto opera2 = new OperationLogDto();
            opera2.setCreateBy(currentUsername);
            opera2.setDomainId(couponsBatch.getId());
            opera2.setOperateDesc("修改优惠券");
            this.editLog(opera2);

            Boolean delete = redisTemplate.delete(CouponsConstants.ACTIVITY_COUPON_PREFIX + "-1" + ":" + couponsCenter.getBatchId() + ":" + couponsCenter.getId());
            if (delete != null && !delete) {
                throw new BaseException(BusinessMessage.ACTIVITY_Time_DELETE_ERROR);
            }
        }

        log.info("结束删除限时抢优惠券");
        return Response.success(couponsCenter.getId());

    }


    /**
     * 修改限时抢优惠券
     * zyf
     * 2020/7/24
     *
     * @param id              优惠券活动批次id
     * @param dto             限时抢优惠活动修改入参
     * @param userId          用户id
     * @param currentUsername 用户
     */
    @Override
    @Transactional
    public Response editTimeCouponsCenter(Long id, CouponsCenterEditTimeDto dto, Long userId, String currentUsername) {


        log.info("开始修改优惠券限时抢活动");

        CouponsCenter center = this.couponsCenterMapper.selectOne(new QueryWrapper<CouponsCenter>().eq("id", id).eq("is_delete", 0));

        CouponsBatch couponsBatch = this.couponsBatchMapper.selectById(center.getBatchId());

        //                校验券批次的数量是否大于0
        if (couponsBatch.getStockNum() <= 0) {
            throw new BaseException(BusinessMessage.COUPON_BATCH_NOT_ENOUGH_ERROR);
        }
        //        券批次有效期开始时间=<活动有效期<=券批次有效期结束时间
        boolean res = !((dto.getStartTime().isAfter(couponsBatch.getStartTime().toLocalDate()) || dto.getStartTime().isEqual(couponsBatch.getStartTime().toLocalDate())) && (dto.getEndTime().isBefore(couponsBatch.getEndTime().toLocalDate()) || dto.getEndTime().isEqual(couponsBatch.getEndTime().toLocalDate())));
        //       校验批次券的有效期在活动的有效期间
        if (res) {
            throw new BaseException(BusinessMessage.COUPON_TIME_OUT_ERROR);
        }
        //        单用户发放数量必须小于优惠券每人最大可领取数量
        if (dto.getLimitNum() > couponsBatch.getLimitNum() || dto.getLimitNum() <= 0) {
            throw new BaseException(BusinessMessage.COUPON_NUM_ERROR);
        }
        center.setLimitNum(dto.getLimitNum());
        center.setTotalNum(dto.getTotalNum());
        if (dto.getTotalNum() > couponsBatch.getStockNum()) {
            //      分布式锁
            RLock lock = redissonClient.getLock(CouponsConstants.ACTIVITY_COUPON_TIME_STOCK_LOCK);
//        加锁
            lock.lock();
            try {
                redisTemplate.opsForValue().set(CouponsConstants.ACTIVITY_COUPON_PREFIX + "-1" + ":" + center.getBatchId() + ":" + center.getId(), couponsBatch.getStockNum().toString());
            } finally {
                lock.unlock();
            }
            //            修改优惠券批次数量
            couponsBatch.setStockNum(0);
            couponsBatch.setUpdateBy(userId);
            couponsBatch.setUpdateTime(LocalDateTime.now());
            this.couponsBatchMapper.updateById(couponsBatch);

            //            记录日志惠券数据修改日志
            //优惠券修改完成之后，录入优惠券操作日志表
            OperationLogDto opera1 = new OperationLogDto();
            opera1.setCreateBy(currentUsername);
            opera1.setDomainId(couponsBatch.getId());
            opera1.setOperateDesc("修改优惠券");
            this.editLog(opera1);
        } else {
            //      分布式锁
            RLock lock = redissonClient.getLock(CouponsConstants.ACTIVITY_COUPON_TIME_STOCK_LOCK);
//        加锁
            lock.lock();
            try {
                redisTemplate.opsForValue().set(CouponsConstants.ACTIVITY_COUPON_PREFIX + "-1" + ":" + center.getBatchId() + ":" + center.getId(), dto.getTotalNum().toString());
            } finally {
                lock.unlock();
            }
            //            修改优惠券批次数量
            couponsBatch.setStockNum(couponsBatch.getStockNum() - dto.getTotalNum());
            couponsBatch.setUpdateBy(userId);
            couponsBatch.setUpdateTime(LocalDateTime.now());
            this.couponsBatchMapper.updateById(couponsBatch);

            //            记录日志惠券数据修改日志
            //优惠券修改完成之后，录入优惠券操作日志表
            OperationLogDto opera1 = new OperationLogDto();
            opera1.setCreateBy(currentUsername);
            opera1.setDomainId(couponsBatch.getId());
            opera1.setOperateDesc("修改优惠券");
            this.editLog(opera1);
        }
        center.setBeginTime(dto.getBeginTime());
        center.setStartTime(dto.getStartTime());
        center.setEndTime(dto.getEndTime());
        center.setOrderSrot(dto.getOrderSrot());
        center.setUpdateBy(userId);
        center.setUpdateTime(LocalDateTime.now());

        this.couponsCenterMapper.updateById(center);

        //            记录活动修改日志
        OperationLogDto opera2 = new OperationLogDto();
        opera2.setCreateBy(currentUsername);
        opera2.setDomainId(center.getId());
        opera2.setOperateDesc("修改限时抢活动");
        this.editActivityLog(opera2);


        log.info("结束修改优惠券限时抢活动");
        return Response.success(center.getId());
    }

    /**
     * 新增领券活动
     * zyf
     * 2020/7/24
     *
     * @param userId          用户id
     * @param currentUsername 用户
     * @param dto             领券入参
     */
    @Override
    @Transactional
    public Response addReveiceCouponsCenter(Long userId, String currentUsername, CouponsCenterAddReceiveDto dto) {

        log.info("新增领券活动开始");
        CouponsBatch couponsBatch = this.couponsBatchMapper.selectById(dto.getCouponsId());
        validParamReceive(dto, couponsBatch);

        CouponsCenter center = new CouponsCenter();
        center.setActivityId(-2);
        center.setApplyId(userId);
        center.setBatchId(dto.getCouponsId());
        center.setBatchName(dto.getBatchName());
        center.setStartTime(dto.getStartTime());
        center.setEndTime(dto.getEndTime());
        center.setCouponsType(2);  //1 限时抢  2领券
        center.setLimitNum(dto.getLimitNum());
        center.setCountNum(dto.getCountNum());

        center.setCreateBy(userId);
        center.setCreateTime(LocalDateTime.now());
        this.couponsCenterMapper.insert(center);

        //            记录活动修改日志
        OperationLogDto opera2 = new OperationLogDto();
        opera2.setCreateBy(currentUsername);
        opera2.setDomainId(center.getId());
        opera2.setOperateDesc("添加领券活动");
        this.editActivityLog(opera2);


        redisTemplate.opsForValue().set(CouponsConstants.ACTIVITY_COUPON_PREFIX + "-2" + ":" + dto.getCouponsId() + ":" + center.getId(), dto.getCountNum().toString());

//            修改优惠券批次数量
        couponsBatch.setStockNum(couponsBatch.getStockNum() - dto.getCountNum());

        this.couponsBatchMapper.updateById(couponsBatch);

        //            记录日志惠券数据修改日志
        //优惠券修改完成之后，录入优惠券操作日志表
        OperationLogDto opera1 = new OperationLogDto();
        opera1.setCreateBy(currentUsername);
        opera1.setDomainId(couponsBatch.getId());
        opera1.setOperateDesc("修改优惠券");
        this.editLog(opera1);

        log.info("新增领券活动结束");
        return Response.success(center.getId());

    }

    /**
     * 删除领券优惠券
     * zyf
     * 2020/7/24
     *
     * @param userId          用户id
     * @param currentUsername 用户
     * @param id              领券id
     */
    @Override
    @Transactional
    public Response delReceiveCouponsCenter(Long userId, String currentUsername, Long id) {


        log.info("开始删除领用券活动");

//            查询出领券活动信息
        CouponsCenter couponsCenter = this.couponsCenterMapper.selectOne(new QueryWrapper<CouponsCenter>().eq("id", id).eq("is_delete", 0));
        if (couponsCenter == null) {
            throw new BaseException(BusinessMessage.ACTIVITY_CENTER_NOT_EXISTS_ERROR);
        }
        //            同时删除redis中活动库存
        String s = redisTemplate.opsForValue().get(CouponsConstants.ACTIVITY_COUPON_PREFIX + "-2" + ":" + couponsCenter.getBatchId() + ":" + couponsCenter.getId());
        if (s != null) {
            redisTemplate.delete(CouponsConstants.ACTIVITY_COUPON_PREFIX + "-2" + ":" + couponsCenter.getBatchId() + ":" + couponsCenter.getId());
        }
        //            删除之前，将活动库存数量归还优惠券
        CouponsBatch couponsBatch = this.couponsBatchMapper.selectById(couponsCenter.getBatchId());

        couponsBatch.setStockNum(couponsBatch.getStockNum() + couponsCenter.getCountNum());

        couponsBatch.setUpdateBy(userId);
        couponsBatch.setUpdateTime(LocalDateTime.now());
        //                修改完成优惠券数据
        this.couponsBatchMapper.updateById(couponsBatch);

//            记录日志惠券数据修改日志
        //优惠券修改完成之后，录入优惠券操作日志表
        OperationLogDto opera1 = new OperationLogDto();
        opera1.setCreateBy(currentUsername);
        opera1.setDomainId(couponsBatch.getId());
        opera1.setOperateDesc("修改优惠券");
        this.editLog(opera1);

        couponsCenter.setUpdateBy(userId);
        couponsCenter.setUpdateTime(LocalDateTime.now());
        couponsCenter.setIsDelete(1);

        this.couponsCenterMapper.updateById(couponsCenter);

//            记录活动修改日志
        OperationLogDto opera2 = new OperationLogDto();
        opera2.setCreateBy(currentUsername);
        opera2.setDomainId(couponsCenter.getId());
        opera2.setOperateDesc("删除领券活动");
        this.editActivityLog(opera2);

        log.info("结束删除领用券活动");

        return Response.success(couponsCenter.getId());

    }

    /**
     * 修改领用券信息
     * zyf
     * 2020/7/24
     *
     * @param userId 用户id
     * @param id     领券id
     * @param dto    修改领券信息入参
     */
    @Override
    @Transactional
    public Response editReceiveCouponsCenter(Long userId, String currentUsername, Long id, CouponsCenterEditReceiveDto dto) {


        log.info("开始修改领券信息");

        //修改保存，需先判断修改之后的活动总数量是否大于等于活动剩余数量
        CouponsCenter center = this.couponsCenterMapper.selectOne(new QueryWrapper<CouponsCenter>().eq("id", id).eq("is_delete", 0));

        CouponsBatch couponsBatch = this.couponsBatchMapper.selectById(center.getBatchId());

        //                校验券批次的数量是否大于0
        if (couponsBatch.getStockNum() <= 0) {
            throw new BaseException(BusinessMessage.COUPON_BATCH_NOT_ENOUGH_ERROR);
        }
        //        券批次有效期开始时间=<活动有效期<=券批次有效期结束时间
        boolean res = !((dto.getStartTime().isAfter(couponsBatch.getStartTime().toLocalDate()) || dto.getStartTime().isEqual(couponsBatch.getStartTime().toLocalDate())) && (dto.getEndTime().isBefore(couponsBatch.getEndTime().toLocalDate()) || dto.getEndTime().isEqual(couponsBatch.getEndTime().toLocalDate())));
        //       校验批次券的有效期在活动的有效期间
        if (res) {
            throw new BaseException(BusinessMessage.COUPON_TIME_OUT_ERROR);
        }
//        单用户发放数量必须小于优惠券每人最大可领取数量
        if ((couponsBatch.getLimitNum() != null && dto.getLimitNum() > couponsBatch.getLimitNum()) || dto.getLimitNum() <= 0) {
            throw new BaseException(BusinessMessage.COUPON_NUM_ERROR);
        }
        //                校验活动总数量不能超过优惠券剩余数量
        if (dto.getCountNum() > couponsBatch.getStockNum()) {
            throw new BaseException(BusinessMessage.Activity_NUM_ERROR);
        }
        //            更新优惠券信息
        //    同时更新优惠券剩余数量 进一步扣减  100   50
        //    同时更新优惠券剩余数量  进一步添加 100   200
        if (dto.getCountNum() >= center.getCountNum()) {
            couponsBatch.setStockNum(couponsBatch.getStockNum() - (dto.getCountNum() - center.getCountNum()));
        } else {
            couponsBatch.setStockNum(couponsBatch.getStockNum() + (center.getCountNum() - dto.getCountNum()));
        }

        couponsBatch.setUpdateBy(userId);
        couponsBatch.setUpdateTime(LocalDateTime.now());
        //                修改完成优惠券数据
        this.couponsBatchMapper.updateById(couponsBatch);

//            记录日志惠券数据修改日志
        //优惠券修改完成之后，录入优惠券操作日志表
        OperationLogDto opera1 = new OperationLogDto();
        opera1.setCreateBy(currentUsername);
        opera1.setDomainId(couponsBatch.getId());
        opera1.setOperateDesc("修改优惠券");
        this.editLog(opera1);

        center.setCountNum(dto.getCountNum());
        center.setLimitNum(dto.getLimitNum());
        center.setStartTime(dto.getStartTime());
        center.setEndTime(dto.getEndTime());
        center.setUpdateBy(userId);
        center.setUpdateTime(LocalDateTime.now());

        this.couponsCenterMapper.updateById(center);
        //      分布式锁
        RLock lock = redissonClient.getLock(CouponsConstants.ACTIVITY_COUPON_GET_STOCK_LOCK);
//        加锁
        lock.lock();
        try {
            redisTemplate.opsForValue().set(CouponsConstants.ACTIVITY_COUPON_PREFIX + "-2" + ":" + center.getBatchId() + ":" + center.getId(), dto.getCountNum().toString());
        } finally {
            lock.unlock();
        }

        log.info("结束修改领券信息");
        return Response.success(center.getId());


    }

    /**
     * 定时将限时抢活动的库存进行补充
     *
     * @return void
     */
    @Override
    public void updateTimeActivityStock() {
//        查询是否有正在进行的限时抢活动,当前时间在活动范围内
        List<CouponsCenter> couponsCenters = this.couponsCenterMapper.selectList(new QueryWrapper<CouponsCenter>()
                .le("start_time", LocalDate.now()).ge("end_time", LocalDate.now()));

        if (couponsCenters != null && couponsCenters.size() > 0) {

            for (CouponsCenter couponsCenter : couponsCenters) {
//                限时抢处理库存
                if (couponsCenter.getCouponsType() == 1) {
                    String num = redisTemplate.opsForValue().get(CouponsConstants.ACTIVITY_COUPON_PREFIX + "-1" + ":" + couponsCenter.getBatchId() + ":" + couponsCenter.getId());
                    if (num != null) {
                        Integer i = Integer.parseInt(num);
                        //        查询限时抢活动的库存，校验库存,如果还有则补齐每日最大总数从批次券
                        if (i < couponsCenter.getTotalNum()) {
                            CouponsBatch couponsBatch = this.couponsBatchMapper.selectOne(new QueryWrapper<CouponsBatch>().eq("id", couponsCenter.getBatchId()));
                            int res = couponsBatch.getStockNum() + i;
                            //        如果批次券数量不够补齐最大数量，则将剩余数量填家到活动库存即可
                            if (res < couponsCenter.getTotalNum()) {
                                couponsBatch.setStockNum(0);
                                couponsBatch.setUpdateBy(123456789L);
                                couponsBatch.setUpdateTime(LocalDateTime.now());
                                this.couponsBatchMapper.updateById(couponsBatch);

                                //            记录日志惠券数据修改日志
                                //优惠券修改完成之后，录入优惠券操作日志表
                                OperationLogDto opera2 = new OperationLogDto();
                                opera2.setCreateBy("广电测试");
                                opera2.setDomainId(couponsBatch.getId());
                                opera2.setOperateDesc("修改优惠券");
                                this.editLog(opera2);

//                            同时修改限时抢活动的库存
                                redisTemplate.opsForValue().set(CouponsConstants.ACTIVITY_COUPON_PREFIX + "-2" + ":" + couponsCenter.getBatchId() + ":" + couponsCenter.getId(), String.valueOf(res));
                            } else {
                                Integer res2 = couponsBatch.getStockNum() - (couponsCenter.getTotalNum() - i);
                                couponsBatch.setStockNum(res2);
                                couponsBatch.setUpdateBy(123456789L);
                                couponsBatch.setUpdateTime(LocalDateTime.now());
                                this.couponsBatchMapper.updateById(couponsBatch);

                                //            记录日志惠券数据修改日志
                                //优惠券修改完成之后，录入优惠券操作日志表
                                OperationLogDto opera2 = new OperationLogDto();
                                opera2.setCreateBy("广电测试");
                                opera2.setDomainId(couponsBatch.getId());
                                opera2.setOperateDesc("修改优惠券");
                                this.editLog(opera2);

                                // 修改限时抢活动的库存为最大数量
                                redisTemplate.opsForValue().set(CouponsConstants.ACTIVITY_COUPON_PREFIX + "-2" + ":" + couponsCenter.getBatchId() + ":" + couponsCenter.getId(), String.valueOf(couponsCenter.getTotalNum()));
                            }
                        }
                    }
                }
                if (couponsCenter.getCouponsType() == 2) {
                    //           领券处理库存
                    String num = redisTemplate.opsForValue().get(CouponsConstants.ACTIVITY_COUPON_PREFIX + "-2" + ":" + couponsCenter.getBatchId() + ":" + couponsCenter.getId());
                    if (num != null) {
//                        将剩余库存放入到数据库进行保存
                        couponsCenter.setSurplusNum(Integer.parseInt(num));

                        couponsCenter.setUpdateBy(123456789L);
                        couponsCenter.setUpdateTime(LocalDateTime.now());

                        this.couponsCenterMapper.updateById(couponsCenter);

                        //            记录日志惠券数据修改日志
                        //优惠券修改完成之后，录入优惠券操作日志表
                        OperationLogDto opera1 = new OperationLogDto();
                        opera1.setCreateBy("广电测试");
                        opera1.setDomainId(couponsCenter.getId());
                        opera1.setOperateDesc("修改领券活动");
                        this.editActivityLog(opera1);

//                        同时删除领券的redis库存
                        Boolean delete = redisTemplate.delete(CouponsConstants.ACTIVITY_COUPON_PREFIX + "-2" + ":" + couponsCenter.getBatchId() + ":" + couponsCenter.getId());
                        if (delete != null && !delete) {
                            throw new BaseException(BusinessMessage.ACTIVITY_GRANT_DELETE_ERROR);
                        }

                    }
                }
            }

        }

    }

    /**
     * 通用日志写入方法
     * zyf
     * 2020/07/22
     *
     * @param dto 日志入参
     */
    private Response editLog(OperationLogDto dto) {
        try {
            log.info("开始写入日志操作表");
            OperationLog operationLog = new OperationLog();
            operationLog.setType(0);
            operationLog.setCreateBy(dto.getCreateBy());
            operationLog.setCreateTime(LocalDateTime.now());
            operationLog.setDomainId(dto.getDomainId());
            operationLog.setOperateDesc(dto.getOperateDesc());
            operationLog.setOperateType(0);
            operationLog.setRemark(dto.getRemark());
            this.operationLogMapper.insert(operationLog);
            log.info("日志操作表填写完成");
            return Response.success();
        } catch (Exception e) {
            log.error("写入日志操作表失败", e);
            throw new BaseException(BusinessMessage.OPERATION_LOG_WRITE_ERROR);
        }
    }

    /**
     * 通用日志写入方法
     * zyf
     * 2020/07/22
     *
     * @param dto 日志入参
     */
    private Response editActivityLog(OperationLogDto dto) {
        try {
            log.info("开始写入日志操作表");
            OperationLog operationLog = new OperationLog();
            operationLog.setType(1);
            operationLog.setCreateBy(dto.getCreateBy());
            operationLog.setCreateTime(LocalDateTime.now());
            operationLog.setDomainId(dto.getDomainId());
            operationLog.setOperateDesc(dto.getOperateDesc());
            operationLog.setOperateType(0);
            operationLog.setRemark(dto.getRemark());
            this.operationLogMapper.insert(operationLog);
            log.info("日志操作表填写完成");
            return Response.success();
        } catch (Exception e) {
            log.error("写入日志操作表失败", e);
            throw new BaseException(BusinessMessage.OPERATION_LOG_WRITE_ERROR);
        }
    }

}
